home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Extensions / img / dither.c next >
C/C++ Source or Header  |  1995-12-21  |  7KB  |  247 lines

  1. /*
  2. ** dither - Dither a 24-bit color image to an 8 bit mapped image.
  3. **
  4. ** Jack Jansen, CWI, 1995.
  5. **
  6. ** Modified from ppmquant.c, which is
  7. ** Copyright (C) 1989, 1991 by Jef Poskanzer.
  8. **
  9. ** Permission to use, copy, modify, and distribute this software and its
  10. ** documentation for any purpose and without fee is hereby granted, provided
  11. ** that the above copyright notice appear in all copies and that both that
  12. ** copyright notice and this permission notice appear in supporting
  13. ** documentation.  This software is provided "as is" without express or
  14. ** implied warranty.
  15. */
  16.  
  17. #include "Python.h"
  18. #include "mppmcmap.h"
  19.  
  20. #define MAXCOLORS 32767
  21.  
  22. int
  23. mppm_dither(pixels, cols, rows, colormap, newcolors, floyd, result)
  24.     pixel *pixels;
  25.     int cols, rows;
  26.     pixel *colormap;
  27.     int newcolors;
  28.     int floyd;
  29.     unsigned char *result;
  30. {
  31. #if 0
  32. int
  33. main( argc, argv )
  34.     int argc;
  35.     char* argv[];
  36.     {
  37.     FILE* ifp;
  38.     pixel** pixels;
  39.     pixel** mappixels;
  40.     register pixel* pP;
  41.     int argn, rows, cols, maprows, mapcols, row;
  42.     register int col, limitcol;
  43.     pixval maxval, newmaxval, mapmaxval;
  44.     int newcolors, colors;
  45.     register int ind;
  46.     colorhist_vector chv, colormap;
  47.     int floyd;
  48.     char* usage = "[-floyd|-fs] <ncolors> [ppmfile]\n                 [-floyd|-fs] -map mapfile [ppmfile]";
  49. #endif
  50.     colorhash_table cht;
  51.     int usehash;
  52.     long thispixel;
  53.     int ind;
  54.     long* thisrerr;
  55.     long* nextrerr;
  56.     long* thisgerr;
  57.     long* nextgerr;
  58.     long* thisberr;
  59.     long* nextberr;
  60.     long* temperr;
  61.     register long sr, sg, sb, err;
  62. #define FS_SCALE 1024
  63.     int fs_direction;
  64.     int col, limitcol, row;
  65.     register pixel* pP;
  66.  
  67.     /*
  68.     ** Step 4: map the colors in the image to their closest match in the
  69.     ** new colormap, and write 'em out.
  70.     */
  71.     cht = mppm_alloccolorhash( );
  72.     usehash = 1;
  73.     if ( floyd )
  74.     {
  75.     /* Initialize Floyd-Steinberg error vectors. */
  76.     thisrerr = (long*) calloc( cols + 2, sizeof(long) );
  77.     nextrerr = (long*) calloc( cols + 2, sizeof(long) );
  78.     thisgerr = (long*) calloc( cols + 2, sizeof(long) );
  79.     nextgerr = (long*) calloc( cols + 2, sizeof(long) );
  80.     thisberr = (long*) calloc( cols + 2, sizeof(long) );
  81.     nextberr = (long*) calloc( cols + 2, sizeof(long) );
  82.     if ( !thisrerr || !nextrerr || !thisgerr ||
  83.          !nextgerr || !thisberr || !nextberr )
  84.         return -1;
  85. #ifdef macintosh
  86.     srand(time(0));
  87. #else
  88.     srand( (int) ( time( 0 ) ^ getpid( ) ) );
  89. #endif
  90.     for ( col = 0; col < cols + 2; ++col )
  91.         {
  92.         thisrerr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
  93.         thisgerr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
  94.         thisberr[col] = rand( ) % ( FS_SCALE * 2 ) - FS_SCALE;
  95.         /* (random errors in [-1 .. 1]) */
  96.         }
  97.     fs_direction = 1;
  98.     }
  99.     for ( row = 0; row < rows; ++row )
  100.     {
  101.     if ( floyd )
  102.         for ( col = 0; col < cols + 2; ++col )
  103.         nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
  104.     if ( ( ! floyd ) || fs_direction )
  105.         {
  106.         col = 0;
  107.         limitcol = cols;
  108.         pP = &pixels[row*cols];
  109.         }
  110.     else
  111.         {
  112.         col = cols - 1;
  113.         limitcol = -1;
  114.         pP = &(pixels[row*cols+col]);
  115.         }
  116.     do
  117.         {
  118.         if ( floyd )
  119.         {
  120.         /* Use Floyd-Steinberg errors to adjust actual color. */
  121.         sr = MPPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
  122.         sg = MPPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
  123.         sb = MPPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
  124.         if ( sr < 0 ) sr = 0;
  125.         else if ( sr > MAXVAL ) sr = MAXVAL;
  126.         if ( sg < 0 ) sg = 0;
  127.         else if ( sg > MAXVAL ) sg = MAXVAL;
  128.         if ( sb < 0 ) sb = 0;
  129.         else if ( sb > MAXVAL ) sb = MAXVAL;
  130.         MPPM_ASSIGN( thispixel, sr, sg, sb );
  131.         } else {
  132.         thispixel = *pP;
  133.         }
  134.  
  135.         /* Check hash table to see if we have already matched this color. */
  136.         ind = mppm_lookupcolor( cht, &thispixel );
  137.         if ( ind == -1 )
  138.         { /* No; search colormap for closest match. */
  139.         register int i, r1, g1, b1, r2, g2, b2;
  140.         register long dist, newdist;
  141.         r1 = MPPM_GETR( thispixel );
  142.         g1 = MPPM_GETG( thispixel );
  143.         b1 = MPPM_GETB( thispixel );
  144.         dist = 2000000000;
  145.         for ( i = 0; i < newcolors; ++i )
  146.             {
  147.             r2 = MPPM_GETR( colormap[i] );
  148.             g2 = MPPM_GETG( colormap[i] );
  149.             b2 = MPPM_GETB( colormap[i] );
  150.             newdist = ( r1 - r2 ) * ( r1 - r2 ) +
  151.                   ( g1 - g2 ) * ( g1 - g2 ) +
  152.                   ( b1 - b2 ) * ( b1 - b2 );
  153.             if ( newdist < dist )
  154.             {
  155.             ind = i;
  156.             dist = newdist;
  157.             }
  158.             }
  159.         if ( usehash )
  160.             {
  161.             if ( mppm_addtocolorhash( cht, &thispixel, ind ) < 0 )
  162.             {
  163.             pm_message(
  164.            "out of memory adding to hash table, proceeding without it");
  165.             usehash = 0;
  166.             }
  167.             }
  168.         }
  169.  
  170.         if ( floyd )
  171.         {
  172.         /* Propagate Floyd-Steinberg error terms. */
  173.         if ( fs_direction )
  174.             {
  175.             err = ( sr - (long) MPPM_GETR( colormap[ind] ) ) * FS_SCALE;
  176.             thisrerr[col + 2] += ( err * 7 ) / 16;
  177.             nextrerr[col    ] += ( err * 3 ) / 16;
  178.             nextrerr[col + 1] += ( err * 5 ) / 16;
  179.             nextrerr[col + 2] += ( err     ) / 16;
  180.             err = ( sg - (long) MPPM_GETG( colormap[ind] ) ) * FS_SCALE;
  181.             thisgerr[col + 2] += ( err * 7 ) / 16;
  182.             nextgerr[col    ] += ( err * 3 ) / 16;
  183.             nextgerr[col + 1] += ( err * 5 ) / 16;
  184.             nextgerr[col + 2] += ( err     ) / 16;
  185.             err = ( sb - (long) MPPM_GETB( colormap[ind] ) ) * FS_SCALE;
  186.             thisberr[col + 2] += ( err * 7 ) / 16;
  187.             nextberr[col    ] += ( err * 3 ) / 16;
  188.             nextberr[col + 1] += ( err * 5 ) / 16;
  189.             nextberr[col + 2] += ( err     ) / 16;
  190.             }
  191.         else
  192.             {
  193.             err = ( sr - (long) MPPM_GETR( colormap[ind] ) ) * FS_SCALE;
  194.             thisrerr[col    ] += ( err * 7 ) / 16;
  195.             nextrerr[col + 2] += ( err * 3 ) / 16;
  196.             nextrerr[col + 1] += ( err * 5 ) / 16;
  197.             nextrerr[col    ] += ( err     ) / 16;
  198.             err = ( sg - (long) MPPM_GETG( colormap[ind] ) ) * FS_SCALE;
  199.             thisgerr[col    ] += ( err * 7 ) / 16;
  200.             nextgerr[col + 2] += ( err * 3 ) / 16;
  201.             nextgerr[col + 1] += ( err * 5 ) / 16;
  202.             nextgerr[col    ] += ( err     ) / 16;
  203.             err = ( sb - (long) MPPM_GETB( colormap[ind] ) ) * FS_SCALE;
  204.             thisberr[col    ] += ( err * 7 ) / 16;
  205.             nextberr[col + 2] += ( err * 3 ) / 16;
  206.             nextberr[col + 1] += ( err * 5 ) / 16;
  207.             nextberr[col    ] += ( err     ) / 16;
  208.             }
  209.         }
  210.  
  211.         /* XXXX *pP = colormap[ind].color; */
  212.         result[col] = ind;
  213.  
  214.         if ( ( ! floyd ) || fs_direction )
  215.         {
  216.         ++col;
  217.         ++pP;
  218.         }
  219.         else
  220.         {
  221.         --col;
  222.         --pP;
  223.         }
  224.         }
  225.     while ( col != limitcol );
  226.  
  227.     if ( floyd )
  228.         {
  229.         temperr = thisrerr;
  230.         thisrerr = nextrerr;
  231.         nextrerr = temperr;
  232.         temperr = thisgerr;
  233.         thisgerr = nextgerr;
  234.         nextgerr = temperr;
  235.         temperr = thisberr;
  236.         thisberr = nextberr;
  237.         nextberr = temperr;
  238.         fs_direction = ! fs_direction;
  239.         }
  240.  
  241.     /*XXXX mppm_writeppmrow( stdout, pixels[row], cols, MAXVAL, 0 ); */
  242.     result += cols;
  243.     }
  244.     /* XXXX Free temp data XXXX */
  245.     return 0;
  246.     }
  247.